package DispatchSys;

import java.util.Date;
import java.util.LinkedList;
import java.util.List;

import Shared.ERState;
import Shared.Form;
import Shared.MapPosition;

/**
 * Structure holding the emergency from the software point of view.
 */


public class ERInfo extends Form implements Comparable<ERInfo> {

	// Status of the emergency
	private ERState status;

	// Time for an emergency to be finished or aborted (defined arbitrarily)
	public static final int TIME_INTERVENTION = 100000;

	// All the forms received for this emergency
	private List<Form> forms;

	private Date notificationTime;
	private Date finishedTime;

	/**
	 * Creates an emergency from the software point of view. The emergency is
	 * unassigned.
	 * 
	 * @param calleeName
	 *            The name of the person who called
	 * @param calleeNumber
	 *            The phone number of the person who called
	 * @param calleePosition
	 *            The position of the person who called
	 * @param isUrgent
	 *            True if the emergency requires an equipped ambulance.
	 * @param time
	 *            The timestamp for when the emergency was notified
	 * @param location
	 *            The location of the emergency
	 * @param description
	 *            The description of the emergency
	 */

	public ERInfo(String calleeName, String calleeNumber, MapPosition calleePosition, boolean isUrgent, Date time,
			MapPosition location, String description) {
		super(calleeName, calleeNumber, calleePosition, isUrgent, location, description);

		this.status = ERState.UNASSIGNED;
		this.notificationTime = time;
		this.forms = new LinkedList<Form>();
	}

	/**
	 * Checks if the emergency is unassigned.
	 * 
	 * @return True if unassigned, false otherwise
	 */
	synchronized public boolean isUnAssigned() {
		return this.status == ERState.UNASSIGNED;
	}

	/**
	 * Checks if the emergency is assigned.
	 * 
	 * @return True if assigned, false otherwise
	 */
	synchronized public boolean isAssigned() {
		return this.status == ERState.ASSIGNED;
	}

	/**
	 * Set the status of the emergency to assigned or unassigned
	 * 
	 * @param a
	 *            - true to set the status to assigned, false for unassigned
	 */

	synchronized public void setAssigned(boolean a) {
		this.status = a ? ERState.ASSIGNED : ERState.UNASSIGNED;
	}

	/**
	 * Compares this emergency to another emergency. Provides a way to order
	 * emergencies used to know which one comes first, according to a priority
	 * rule.
	 * 
	 * @param anotherEr
	 *            The emergency to be compared with
	 * @return an integer < 0 if this one comes first, an integer > 0 if the
	 *         other emergency comes first or 0 if they have the same priority.
	 */
	synchronized public int compareTo(ERInfo anotherEr) {

		if (this.isUrgent() && !anotherEr.isUrgent()) {
			return -1; // This one is more urgent.
		} else if (anotherEr.isUrgent() && !this.isUrgent()) {
			return 1; // the other is more urgent
		} else {
			// Compares the notification time
			return this.getNotificationTime().compareTo(anotherEr.getNotificationTime());
		}

	}

	/**
	 * Emergencies are considered equal if they are located at the same location
	 * and the elapsed time between the 2 notifications are less than TIME_INTERVENTION.
	 * 
	 * @param anotherER
	 *            - the emergency to be compared with
	 * @return true if equals, false otherwise
	 */

	public synchronized boolean equals(ERInfo anotherER) {
		if (this.getLocation().getCoordinates()[0] == anotherER.getLocation().getCoordinates()[0]
				&& this.getLocation().getCoordinates()[1] == anotherER.getLocation().getCoordinates()[1]
				&& Math.abs(anotherER.getNotificationTime().getTime() - this.getNotificationTime().getTime()) < TIME_INTERVENTION) {
			return true;
		}
		return false;
	}

	/**
	 * Set the status of this emergency to finished.
	 */
	synchronized public void setFinished() {

		this.status = ERState.FINISHED;
		this.finishedTime = new Date();

	}

	/**
	 * Check if the emergency is already finished
	 * 
	 * @return true if yes, false otherwise
	 */
	public boolean isFinished() {
		return (this.status == ERState.FINISHED);
	}

	/**
	 * Adds a new form corresponding for this emergency
	 * 
	 * @param form
	 *            - a new form to be added for this emergency
	 */
	synchronized public void addForm(Form form) {
		this.forms.add(form);
	}

	/**
	 * Returns the notification time of the emergency
	 */
	public Date getNotificationTime() {
		return this.notificationTime;
	}
	

}
